Author: Katarina Dragicevic (PhD student), Biotech Research and
Innovation Centre, University of Copenhagen
This notebook is about how the Cacoa pipeline was ran on different
Conos objects (P15/P60 excitatory/inhibitory) The same pipeline was used
for all objects and we show here on 1 example how it was done.
- Load Conos object and annotation file. Construct the sample groups
objects. Load color palettes.
#we changed some of the annotation names after we ran Cacoa already
on the objects. This is why we use this recvec to recode the names for
the final plots to make them match those in the paper
recvec <- (setNames(c(‘Sst_Crhr2’, ‘Sst_Crh’, ‘Sst_Nr2f2_Cdh9’,
‘Sst_Hpse’, ‘Sst_Nr2f2_Glra3’, ‘Pvalb_Kcnk10’, ‘Pvalb_Gpc6’,
‘Pvalb_Sema5a’, ‘Pvalb_Gpr149’, ‘Pvalb_Tacr1’, ‘Pvalb_Calb1’,
‘Sst_Necab1’, ‘Vip_Chat’, ‘Pvalb_Htr2c’, ‘Vip_Col15a1’, ‘Id2_Car10’,
‘Id2_Car2’, ‘Id2_Ano3’, ‘Sst_Calb2’, ‘Sst_Piezo2’, ‘Sst_Nr2f2_Necab1’,
‘Sst_Chodl’, ‘Pvalb_Vipr2’, ‘Lamp5_Lhx6’, ‘Vip_Thsd7b’, ‘Lamp5_Lsp1’,
‘Vip_Sgcz’, ‘Vip_Gpc3’, ‘Lamp5_Dock5’, ‘Pvalb_Gabrg1’, ‘Lamp5_Ndst4’),
ci60$cell.groups %>% unique %>% as.character()))
recvec
Sst_Crhr2 Sst_Crh Sst_Nr2f2_Cdh9 Sst_Hpse
"Sst_Crhr2" "Sst_Crh" "Sst_Nr2f2_Cdh9" "Sst_Hpse"
Sst_Nr2f2_Glra3 Pvalb_Sema3e_Kcnk10 Pvalb_Gpc6 Pvalb_Reln_Sema5a
"Sst_Nr2f2_Glra3" "Pvalb_Kcnk10" "Pvalb_Gpc6" "Pvalb_Sema5a"
Pvalb_Gpr149 Pvalb_Tacr1_Il1rapl2 Pvalb_Calb1_Necab1 Sst_Necab1
"Pvalb_Gpr149" "Pvalb_Tacr1" "Pvalb_Calb1" "Sst_Necab1"
Vip_Chat Pvalb_Calb1_Necab1_Htr2c Vip_Col15a1 Id2_Car10
"Vip_Chat" "Pvalb_Htr2c" "Vip_Col15a1" "Id2_Car10"
Id2_Car2 Id2_Ano3 Sst_Calb2 Sst_Mme_Fam114a1
"Id2_Car2" "Id2_Ano3" "Sst_Calb2" "Sst_Piezo2"
Sst_Nr2f2_Necab1 Sst_Chodl Pvalb_Vipr2 Lamp5_Lhx6
"Sst_Nr2f2_Necab1" "Sst_Chodl" "Pvalb_Vipr2" "Lamp5_Lhx6"
Vip_Thsd7b_Prss12 Lamp5_Lsp1 Vip_Sgcz Vip_Gpc3
"Vip_Thsd7b" "Lamp5_Lsp1" "Vip_Sgcz" "Vip_Gpc3"
Lamp5_Dock5 Pvalb_Gabrg1 Lamp5_Ntn1_Ndst4
"Lamp5_Dock5" "Pvalb_Gabrg1" "Lamp5_Ndst4"
#library(cacoa)
#library(qs)
#con <- qread(“inhibitory_p60.qs”, nthreads = 5) #conos object
#anno <- qread(“anno_inhibitory_p60.qs”, nthreads = 1)
#annotation
#sg.pal <- qread(“sg.pal_inhibitory_p60.qs”, nthreads = 1)
#palette for sample groups
#cg.pal <- qread(“cg.pal_inhibitory_p60.qs”, nthreads = 1)
#palette for cell groups
#sg <- qread(“sg_inhibitory_p60.qs”, nthreads = 1) #sample
groups
#how does sg look like?
sg
1014_WT 1099_15q P60_AAM1033_15q_b3 P60_AAM1035_15q_b3 P60_AAM1037_15q_b3 P60_AAM11a_15q_b1
wt 15q 15q 15q 15q 15q
P60_AAM11a_wt_b1 P60_AAM11b_15q_b1 P60_AAM11b_wt_b1 P60_AAM3_wt_b1 P60_AAM8_wt_b1 P60_AAM978_15q_b3
wt 15q wt wt wt 15q
P60_AAMT2_15q_b2 P60_AAMT3_15q_b2 P60_AAMW1_wt_b2 P60_AAMW2_wt_b2
15q 15q wt wt
Levels: 15q wt
#how does sg.pal look like?
sg.pal
15q wt
"dodgerblue2" "black"
#how does cg.pal look like?
cg.pal
Id2_Ano3 Id2_Car10 Id2_Car2 Lamp5_Dock5 Lamp5_Lhx6 Lamp5_Lsp1 Lamp5_Ndst4
"#e07ba9" "#a9e07b" "#857be0" "#a5e07b" "#7be096" "#e0c97b" "#e07bc4"
Pvalb_Calb1 Pvalb_Gabrg1 Pvalb_Gpc6 Pvalb_Gpr149 Pvalb_Htr2c Pvalb_Kcnk10 Pvalb_Sema5a
"#7b92e0" "#a0e07b" "#7be0d4" "#e07b87" "#afe07b" "#ac7be0" "#e07b94"
Pvalb_Tacr1 Pvalb_Vipr2 Sst_Calb2 Sst_Chodl Sst_Crh Sst_Crhr2 Sst_Hpse
"#e0b67b" "#e0997b" "#8fe07b" "#cc7be0" "#7bc1e0" "#b5e07b" "#e07b82"
Sst_Necab1 Sst_Nr2f2_Cdh9 Sst_Nr2f2_Glra3 Sst_Nr2f2_Necab1 Sst_Piezo2 Vip_Chat Vip_Col15a1
"#a67be0" "#e0c27b" "#cbe07b" "#7be0c2" "#7bb3e0" "#e07bc3" "#7b91e0"
Vip_Gpc3 Vip_Sgcz Vip_Thsd7b
"#7be08e" "#7b9ae0" "#e0c17b"
UMAP
#cao$plotEmbedding(color.by = “cell.groups”, font.size = 3)

UMAP colored by sample
#cao$plotEmbedding(color.by = “sample”, font.size = 0)

Cell group proportions
#cao$plotCellGroupSizes()

Cell loadings
#cao$estimateCellLoadings()
p2 %>% ggplot( aes( x = values, y = ind, color = ind)) +
geom_violin(scale = "width",
#fill = "#ededed",
color = NA, aes(fill = ind), alpha = 0.2) +
theme_light() + theme(legend.position = "none") + scale_fill_manual(values = palcomp) +
geom_vline(xintercept = 0, linewidth = 0.1) +
new_scale_fill() +
stat_summary(fun.data = iqr, geom = "errorbar", show.legend = F,
aes(color = ind),
stroke = 0.5, alpha = 0.9,color = "grey30", width = 0.25) +
stat_summary(fun.data = iqr, geom = "point", show.legend = F,
aes(fill = ind),
shape = 23, stroke = 0.5, color = "grey30", alpha = 0.9, size = 2.5) +
scale_fill_manual(values = palcomp)
Warning: Ignoring unknown parameters: `stroke`

Cell Density
#cao$estimateCellDensity(method = “graph”)
#cao$estimateDiffCellDensity(type = “wilcox”, n.cores = 200)
cao$plotDiffCellDensity(type = "wilcox", min.z = 0, adjust.pvalues = T, contours = c("Sst_Nr2f2_Glra3", "Pvalb_Vipr2"), contour.conf = "20%")
| | 0%, ETA NA
|================================================ | 50%, ETA 00:02
|=============================================================================================| 100%, Elapsed 00:03

Expression shifts
#cao$estimateExpressionShiftMagnitudes(top.n.genes = 300)
p3 %>% ggplot( aes( y = value, x = Type, color = Type)) +
geom_violin(scale = "width",
#fill = "#ededed",
color = NA, aes(fill = Type), alpha = 0.2,
trim = F) +
theme_light() + theme(legend.position = "none", axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5), panel.grid.minor = element_blank(), panel.grid.major = element_blank()) + scale_color_manual(values = pal2)+ scale_fill_manual(values = pal2) +
geom_hline(yintercept = 0, linewidth = 0.1) +
stat_summary(fun.data = iqr, geom = "errorbar", show.legend = F, aes(color = Type), shape = 23, stroke = 0.5, alpha = 0.9,color = "grey30", width = 0.25) +
stat_summary(fun.data = iqr, geom = "point", show.legend = F,aes(fill = Type), shape = 23, stroke = 0.5, color = "grey30", alpha = 0.9)
Warning: Ignoring unknown parameters: `shape` and `stroke`

Cluster free expression shifts
#cao$estimateClusterFreeExpressionShifts(n.cores = 200,
gene.selection = “z”, normalize.both = T, n.top.genes = 300)

DEG analysis
#cao$estimateDEPerCellType(n.cores = 100, name = “edgeR”,
n.cells.subsample = 5, resampling.method = “bootstrap”, n.resamplings =
20)


Gene ontology
#cao$estimateOntology(type = “GSEA”, name = “GSEA”, org.db
=org.Mm.eg.db, verbose = T, n.cores = 200, de.name = “edgeR2”)
#cao$estimateOntology(type = "GSEA", name = "GSEA", org.db =org.Mm.eg.db, verbose = T, n.cores = 200, de.name = "edgeR2")
cao$plotOntologyHeatmap(name = "GSEA", genes = "all")
Loading required package: DOSE
DOSE v3.24.2 For help: https://yulab-smu.top/biomedical-knowledge-mining-book/
If you use DOSE in published research, please cite:
Guangchuang Yu, Li-Gen Wang, Guang-Rong Yan, Qing-Yu He. DOSE: an R/Bioconductor package for Disease Ontology Semantic and Enrichment analysis. Bioinformatics 2015, 31(4):608-609


LS0tCnRpdGxlOiAiQ2Fjb2EgYW5hbHlzaXMgd2Fsa3Rocm91Z2giCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCkF1dGhvcjogS2F0YXJpbmEgRHJhZ2ljZXZpYyAoUGhEIHN0dWRlbnQpLCBCaW90ZWNoIFJlc2VhcmNoIGFuZCBJbm5vdmF0aW9uIENlbnRyZSwgVW5pdmVyc2l0eSBvZiBDb3BlbmhhZ2VuCgpUaGlzIG5vdGVib29rIGlzIGFib3V0IGhvdyB0aGUgQ2Fjb2EgcGlwZWxpbmUgd2FzIHJhbiBvbiBkaWZmZXJlbnQgQ29ub3Mgb2JqZWN0cyAoUDE1L1A2MCBleGNpdGF0b3J5L2luaGliaXRvcnkpClRoZSBzYW1lIHBpcGVsaW5lIHdhcyB1c2VkIGZvciBhbGwgb2JqZWN0cyBhbmQgd2Ugc2hvdyBoZXJlIG9uIDEgZXhhbXBsZSBob3cgaXQgd2FzIGRvbmUuIAoKMS4gTG9hZCBDb25vcyBvYmplY3QgYW5kIGFubm90YXRpb24gZmlsZS4gQ29uc3RydWN0IHRoZSBzYW1wbGUgZ3JvdXBzIG9iamVjdHMuIExvYWQgY29sb3IgcGFsZXR0ZXMuCgoKI3dlIGNoYW5nZWQgc29tZSBvZiB0aGUgYW5ub3RhdGlvbiBuYW1lcyBhZnRlciB3ZSByYW4gQ2Fjb2EgYWxyZWFkeSBvbiB0aGUgb2JqZWN0cy4gVGhpcyBpcyB3aHkgd2UgdXNlIHRoaXMgcmVjdmVjIHRvIHJlY29kZSB0aGUgbmFtZXMgZm9yIHRoZSBmaW5hbCBwbG90cyB0byBtYWtlIHRoZW0gbWF0Y2ggdGhvc2UgaW4gdGhlIHBhcGVyCgpyZWN2ZWMgPC0gKHNldE5hbWVzKGMoJ1NzdF9DcmhyMicsICdTc3RfQ3JoJywgJ1NzdF9OcjJmMl9DZGg5JywgJ1NzdF9IcHNlJywgJ1NzdF9OcjJmMl9HbHJhMycsICdQdmFsYl9LY25rMTAnLCAnUHZhbGJfR3BjNicsICdQdmFsYl9TZW1hNWEnLCAnUHZhbGJfR3ByMTQ5JywgJ1B2YWxiX1RhY3IxJywgJ1B2YWxiX0NhbGIxJywgJ1NzdF9OZWNhYjEnLCAnVmlwX0NoYXQnLCAnUHZhbGJfSHRyMmMnLCAnVmlwX0NvbDE1YTEnLCAnSWQyX0NhcjEwJywgJ0lkMl9DYXIyJywgJ0lkMl9Bbm8zJywgJ1NzdF9DYWxiMicsICdTc3RfUGllem8yJywgJ1NzdF9OcjJmMl9OZWNhYjEnLCAnU3N0X0Nob2RsJywgJ1B2YWxiX1ZpcHIyJywgJ0xhbXA1X0xoeDYnLCAnVmlwX1Roc2Q3YicsICdMYW1wNV9Mc3AxJywgJ1ZpcF9TZ2N6JywgJ1ZpcF9HcGMzJywgJ0xhbXA1X0RvY2s1JywgJ1B2YWxiX0dhYnJnMScsICdMYW1wNV9OZHN0NCcpLCBjaTYwJGNlbGwuZ3JvdXBzICU+JSB1bmlxdWUgJT4lIGFzLmNoYXJhY3RlcigpKSkKCmBgYHtyfQojd2UgY2hhbmdlZCBzb21lIG9mIHRoZSBhbm5vdGF0aW9uIG5hbWVzIGFmdGVyIHdlIHJhbiBDYWNvYSBhbHJlYWR5IG9uIHRoZSBvYmplY3RzLiBUaGlzIGlzIHdoeSB3ZSB1c2UgdGhpcyByZWN2ZWMgdG8gcmVjb2RlIHRoZSBuYW1lcyBmb3IgdGhlIGZpbmFsIHBsb3RzIHRvIG1ha2UgdGhlbSBtYXRjaCB0aG9zZSBpbiB0aGUgcGFwZXIKCnJlY3ZlYyA8LSAoc2V0TmFtZXMoYygnU3N0X0NyaHIyJywgJ1NzdF9DcmgnLCAnU3N0X05yMmYyX0NkaDknLCAnU3N0X0hwc2UnLCAnU3N0X05yMmYyX0dscmEzJywgJ1B2YWxiX0tjbmsxMCcsICdQdmFsYl9HcGM2JywgJ1B2YWxiX1NlbWE1YScsICdQdmFsYl9HcHIxNDknLCAnUHZhbGJfVGFjcjEnLCAnUHZhbGJfQ2FsYjEnLCAnU3N0X05lY2FiMScsICdWaXBfQ2hhdCcsICdQdmFsYl9IdHIyYycsICdWaXBfQ29sMTVhMScsICdJZDJfQ2FyMTAnLCAnSWQyX0NhcjInLCAnSWQyX0FubzMnLCAnU3N0X0NhbGIyJywgJ1NzdF9QaWV6bzInLCAnU3N0X05yMmYyX05lY2FiMScsICdTc3RfQ2hvZGwnLCAnUHZhbGJfVmlwcjInLCAnTGFtcDVfTGh4NicsICdWaXBfVGhzZDdiJywgJ0xhbXA1X0xzcDEnLCAnVmlwX1NnY3onLCAnVmlwX0dwYzMnLCAnTGFtcDVfRG9jazUnLCAnUHZhbGJfR2FicmcxJywgJ0xhbXA1X05kc3Q0JyksIGNpNjAkY2VsbC5ncm91cHMgJT4lIHVuaXF1ZSAlPiUgYXMuY2hhcmFjdGVyKCkpKQpyZWN2ZWMKYGBgCgojbGlicmFyeShjYWNvYSkKCiNsaWJyYXJ5KHFzKQoKI2NvbiA8LSBxcmVhZCgiaW5oaWJpdG9yeV9wNjAucXMiLCBudGhyZWFkcyA9IDUpICNjb25vcyBvYmplY3QKCiNhbm5vIDwtIHFyZWFkKCJhbm5vX2luaGliaXRvcnlfcDYwLnFzIiwgbnRocmVhZHMgPSAxKSAjYW5ub3RhdGlvbgoKI3NnLnBhbCA8LSBxcmVhZCgic2cucGFsX2luaGliaXRvcnlfcDYwLnFzIiwgbnRocmVhZHMgPSAxKSAjcGFsZXR0ZSBmb3Igc2FtcGxlIGdyb3VwcwoKI2NnLnBhbCA8LSBxcmVhZCgiY2cucGFsX2luaGliaXRvcnlfcDYwLnFzIiwgbnRocmVhZHMgPSAxKSAjcGFsZXR0ZSBmb3IgY2VsbCBncm91cHMKCiNzZyA8LSBxcmVhZCgic2dfaW5oaWJpdG9yeV9wNjAucXMiLCBudGhyZWFkcyA9IDEpICAjc2FtcGxlIGdyb3VwcwoKCgpgYGB7cn0KbGlicmFyeShjYWNvYSkKbGlicmFyeShxcykKCiNjb24gPC0gcXJlYWQoImluaGliaXRvcnlfcDYwLnFzIiwgbnRocmVhZHMgPSA1KSAjY29ub3Mgb2JqZWN0CiNhbm5vIDwtIHFyZWFkKCJhbm5vX2luaGliaXRvcnlfcDYwLnFzIiwgbnRocmVhZHMgPSAxKSAjYW5ub3RhdGlvbgojc2cucGFsIDwtIHFyZWFkKCJzZy5wYWxfaW5oaWJpdG9yeV9wNjAucXMiLCBudGhyZWFkcyA9IDEpICNwYWxldHRlIGZvciBzYW1wbGUgZ3JvdXBzCiNjZy5wYWwgPC0gcXJlYWQoImNnLnBhbF9pbmhpYml0b3J5X3A2MC5xcyIsIG50aHJlYWRzID0gMSkgI3BhbGV0dGUgZm9yIGNlbGwgZ3JvdXBzCiNzZyA8LSBxcmVhZCgic2dfaW5oaWJpdG9yeV9wNjAucXMiLCBudGhyZWFkcyA9IDEpICAjc2FtcGxlIGdyb3VwcwoKI2hvdyBkb2VzIHNnIGxvb2sgbGlrZT8Kc2cKYGBgCgpgYGB7cn0KI2hvdyBkb2VzIHNnLnBhbCBsb29rIGxpa2U/CnNnLnBhbApgYGAKCgpgYGB7cn0KI2hvdyBkb2VzIGNnLnBhbCBsb29rIGxpa2U/CmNnLnBhbApgYGAKCgpgYGB7cn0KY2FvIDwtIENhY29hJG5ldyhkYXRhLm9iamVjdCA9IGNvbiwgCiAgICAgICAgICAgICAgICAgc2FtcGxlLmdyb3VwcyA9IHNnLCAKICAgICAgICAgICAgICAgICBjZWxsLmdyb3VwcyA9IGFubm8sIAogICAgICAgICAgICAgICAgIHJlZi5sZXZlbCA9ICJ3dCIsIHRhcmdldC5sZXZlbCA9ICIxNXEiLCAKICAgICAgICAgICAgICAgICBzYW1wbGUuZ3JvdXBzLnBhbGV0dGUgPSBzZy5wYWwsIAogICAgICAgICAgICAgICAgIGNlbGwuZ3JvdXBzLnBhbGV0dGUgPSBjZy5wYWwpCmBgYAoKVU1BUAoKI2NhbyRwbG90RW1iZWRkaW5nKGNvbG9yLmJ5ID0gImNlbGwuZ3JvdXBzIiwgZm9udC5zaXplID0gMykKCmBgYHtyfQpjYW8kcGxvdEVtYmVkZGluZyhjb2xvci5ieSA9ICJjZWxsLmdyb3VwcyIsIGZvbnQuc2l6ZSA9IDMpCmBgYApVTUFQIGNvbG9yZWQgYnkgc2FtcGxlCgojY2FvJHBsb3RFbWJlZGRpbmcoY29sb3IuYnkgPSAic2FtcGxlIiwgZm9udC5zaXplID0gMCkKCmBgYHtyfQpjYW8kcGxvdEVtYmVkZGluZyhjb2xvci5ieSA9ICJzYW1wbGUiLCBmb250LnNpemUgPSAwKQpgYGAKQ2VsbCBncm91cCBwcm9wb3J0aW9ucyAKCiNjYW8kcGxvdENlbGxHcm91cFNpemVzKCkKCmBgYHtyfQpjYW8kcGxvdENlbGxHcm91cFNpemVzKCkKYGBgCgoKQ2VsbCBsb2FkaW5ncwoKI2NhbyRlc3RpbWF0ZUNlbGxMb2FkaW5ncygpCgpgYGB7cn0KI2NhbyRlc3RpbWF0ZUNlbGxMb2FkaW5ncygpCnAyIDwtIGNhbyRwbG90Q2VsbExvYWRpbmdzKHNob3cucHZhbHMgPSBGKSRkYXRhCgpsaWJyYXJ5KGRhdGEudGFibGUpCnAyIDwtIGRhdGEudGFibGUocDIpCmx2bCA8LSBwMlssIGFicyhtZWRpYW4odmFsdWVzKSksIGJ5ID0gaW5kXVtvcmRlcigtVjEpLGluZF0gJT4lIGFzLmNoYXJhY3RlcigpCmxldmVscyhwMiRpbmQpIDwtIHJldihsdmwpCnAyJGluZCA8LSBmYWN0b3IocDIkaW5kLCBsZXZlbHMgPSByZXYobHZsKSkKCgoKcDIkaW5kIDwtIGZhY3RvcihyZWNvZGVfZmFjdG9yKHAyJGluZCwhISFyZWN2ZWMpLCBsZXZlbHMgPSBhcy5jaGFyYWN0ZXIodW5pcXVlKCByZWNvZGVfZmFjdG9yKHAyJGluZCwhISFyZWN2ZWMpKSkpCnBhbGNvbXAgPC0gc2V0TmFtZXMoaWZlbHNlKHAyWywgKG1lZGlhbih2YWx1ZXMpKSwgYnkgPSBpbmRdW29yZGVyKC1WMSksVjFdID4gMCwgImRvZGdlcmJsdWUyIiwgImdyZXk2MCIpLCBwMlssIChtZWRpYW4odmFsdWVzKSksIGJ5ID0gaW5kXVtvcmRlcigtVjEpLGluZF0pCnBhbGNvbXAyIDwtIHNldE5hbWVzKGlmZWxzZShwMlssIChtZWRpYW4odmFsdWVzKSksIGJ5ID0gaW5kXVtvcmRlcigtVjEpLFYxXSA+IDAsICJkYXJrYmx1ZSIsICJncmV5NTAiKSwgcDJbLCAobWVkaWFuKHZhbHVlcykpLCBieSA9IGluZF1bb3JkZXIoLVYxKSxpbmRdKQoKbGlicmFyeShnZ25ld3NjYWxlKQpwMiAlPiUgZ2dwbG90KCBhZXMoIHggPSB2YWx1ZXMsIHkgPSBpbmQsIGNvbG9yID0gaW5kKSkgKwogIGdlb21fdmlvbGluKHNjYWxlID0gIndpZHRoIiwgCiAgICAgICAgICAgICAgICAjZmlsbCA9ICIjZWRlZGVkIiwgCiAgICAgICAgICAgICAgICBjb2xvciA9IE5BLCBhZXMoZmlsbCA9IGluZCksIGFscGhhID0gMC4yKSArCiAgdGhlbWVfbGlnaHQoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxjb21wKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXdpZHRoID0gMC4xKSArCiAgbmV3X3NjYWxlX2ZpbGwoKSArIAogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IGlxciwgZ2VvbSA9ICJlcnJvcmJhciIsIHNob3cubGVnZW5kID0gRiwgCiAgICAgICAgICAgICAgIGFlcyhjb2xvciA9IGluZCksIAogICAgICAgICAgICAgICBzdHJva2UgPSAwLjUsIGFscGhhID0gMC45LGNvbG9yID0gImdyZXkzMCIsIHdpZHRoID0gMC4yNSkgKyAKICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBpcXIsIGdlb20gPSAicG9pbnQiLCBzaG93LmxlZ2VuZCA9IEYsCiAgICAgICAgICAgICAgIGFlcyhmaWxsID0gaW5kKSwgCiAgICAgICAgICAgICAgIHNoYXBlID0gMjMsIHN0cm9rZSA9IDAuNSwgY29sb3IgPSAiZ3JleTMwIiwgYWxwaGEgPSAwLjksIHNpemUgPSAyLjUpICsgIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGNvbXApCmBgYAoKQ2VsbCBEZW5zaXR5CgojY2FvJGVzdGltYXRlQ2VsbERlbnNpdHkobWV0aG9kID0gImdyYXBoIikKCiNjYW8kZXN0aW1hdGVEaWZmQ2VsbERlbnNpdHkodHlwZSA9ICJ3aWxjb3giLCBuLmNvcmVzID0gMjAwKQoKYGBge3J9CiNjYW8kZXN0aW1hdGVDZWxsRGVuc2l0eShtZXRob2QgPSAiZ3JhcGgiKQojY2FvJGVzdGltYXRlRGlmZkNlbGxEZW5zaXR5KHR5cGUgPSAid2lsY294Iiwgbi5jb3JlcyA9IDIwMCkKY2FvJHBsb3REaWZmQ2VsbERlbnNpdHkodHlwZSA9ICJ3aWxjb3giLCBtaW4ueiA9IDAsIGFkanVzdC5wdmFsdWVzID0gVCwgIGNvbnRvdXJzID0gYygiU3N0X05yMmYyX0dscmEzIiwgIlB2YWxiX1ZpcHIyIiksIGNvbnRvdXIuY29uZiA9ICIyMCUiKQpgYGAKCgoKRXhwcmVzc2lvbiBzaGlmdHMKCiNjYW8kZXN0aW1hdGVFeHByZXNzaW9uU2hpZnRNYWduaXR1ZGVzKHRvcC5uLmdlbmVzID0gMzAwKQoKYGBge3J9CiN0aGlzIGlzIGFuIGV4YW1wbGUgb24gb25seSBpbmhpYml0b3J5IG5ldXJvbnMsIGluIHRoZSBwYXBlciB3ZSB1c2VkIGJvdGggZXhjaXRhdG9yeSBhbmQgaW5oaWJpdG9yeSBuZXVyb25zIGZvciB0aGUgcGxvdCBhdCBwNjAKCiNjYW8kZXN0aW1hdGVFeHByZXNzaW9uU2hpZnRNYWduaXR1ZGVzKHRvcC5uLmdlbmVzID0gMzAwKQpwYWwyIDwtIGNhbyRjZWxsLmdyb3Vwcy5wYWxldHRlCnAzIDwtIGNhbyRwbG90RXhwcmVzc2lvblNoaWZ0TWFnbml0dWRlcyh0eXBlID0gImJveCIpJGRhdGEKCnAzJFR5cGUgPC0gcmVjb2RlX2ZhY3RvcihwMyRUeXBlLCEhIXJlY3ZlYykKcDMgPC0gZGF0YS50YWJsZShwMykKcDNbLG1lZCA6PSBtZWRpYW4odmFsdWUpLCBieSA9IFR5cGVdCnAzJFR5cGUgPC0gZmFjdG9yKHAzJFR5cGUsIGxldmVscyA9IHAzW29yZGVyKG1lZCldJFR5cGUgJT4lIHVuaXF1ZSAlPiUgYXMuY2hhcmFjdGVyKCkpCgoKcDMgJT4lIGdncGxvdCggYWVzKCB5ID0gdmFsdWUsIHggPSBUeXBlLCBjb2xvciA9IFR5cGUpKSArCiAgZ2VvbV92aW9saW4oc2NhbGUgPSAid2lkdGgiLCAKICAgICAgICAgICAgICAgICNmaWxsID0gIiNlZGVkZWQiLCAKICAgICAgICAgICAgICAgIGNvbG9yID0gTkEsIGFlcyhmaWxsID0gVHlwZSksIGFscGhhID0gMC4yLCAKICAgICAgICAgICAgICB0cmltID0gRikgKwogIHRoZW1lX2xpZ2h0KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgdmp1c3QgPSAwLjUpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBwYWwyKSsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsMikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV3aWR0aCA9IDAuMSkgKwogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IGlxciwgZ2VvbSA9ICJlcnJvcmJhciIsIHNob3cubGVnZW5kID0gRiwgYWVzKGNvbG9yID0gVHlwZSksIHNoYXBlID0gMjMsIHN0cm9rZSA9IDAuNSwgYWxwaGEgPSAwLjksY29sb3IgPSAiZ3JleTMwIiwgd2lkdGggPSAwLjI1KSArIAogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IGlxciwgZ2VvbSA9ICJwb2ludCIsIHNob3cubGVnZW5kID0gRixhZXMoZmlsbCA9IFR5cGUpLCBzaGFwZSA9IDIzLCBzdHJva2UgPSAwLjUsIGNvbG9yID0gImdyZXkzMCIsIGFscGhhID0gMC45KSAKYGBgCkNsdXN0ZXIgZnJlZSBleHByZXNzaW9uIHNoaWZ0cwoKI2NhbyRlc3RpbWF0ZUNsdXN0ZXJGcmVlRXhwcmVzc2lvblNoaWZ0cyhuLmNvcmVzID0gMjAwLCBnZW5lLnNlbGVjdGlvbiA9ICJ6Iiwgbm9ybWFsaXplLmJvdGggPSBULCBuLnRvcC5nZW5lcyA9IDMwMCkKCmBgYHtyfQojY2FvJGVzdGltYXRlQ2x1c3RlckZyZWVFeHByZXNzaW9uU2hpZnRzKG4uY29yZXMgPSAyMDAsIGdlbmUuc2VsZWN0aW9uID0gInoiLCBub3JtYWxpemUuYm90aCA9IFQsIG4udG9wLmdlbmVzID0gMzAwKQpwIDwtIGNhbyRwbG90Q2x1c3RlckZyZWVFeHByZXNzaW9uU2hpZnRzKG1pbi56ID0gMC41LCBidWlsZC5wYW5lbCA9IEYpCmdncGxvdChwW1sxXV0kZGF0YSwgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSBDb2xvcikpICsgZ2VvbV9wb2ludCgpICsgc2NhbGVfZmlsbF9tYW51YWwoKQoKCnAxIDwtIHBbWzFdXSRkYXRhICU+JQogICAgICAgICBhcnJhbmdlKENvbG9yKSAgJT4lIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IENvbG9yKSkgKyBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsgc2NhbGVfY29sb3JfZ3JhZGllbnQyKG1pZCA9ICJncmV5OTAiLCBoaWdoID0gImZpcmVicmljayIsIG1pZHBvaW50ID0gMC4wMDc3LzIsIGxvdyA9ICJncmV5OTUiLCBicmVha3MgPSBjKDAsMC4wMDc3KSwgbmFtZSA9ICJaIHNjb3JlIikgKyB0aGVtZV92b2lkKCkgIyArIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQodGl0bGU9Ilogc2NvcmUiKSkKCnAyIDwtIHBbWzJdXSRkYXRhJT4lCiAgICAgICAgIGFycmFuZ2UoQ29sb3IpICU+JSBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSBDb2xvcikpICsgZ2VvbV9wb2ludChzaXplID0gMC4xKSArIHNjYWxlX2NvbG9yX2dyYWRpZW50MihtaWQgPSAiZ3JleTkwIiwgaGlnaCA9ICJmaXJlYnJpY2siLCBtaWRwb2ludCA9IDAuNiwgbG93ID0gImdyZXk5NSIsICwgbmFtZSA9ICJBZGouWiBzY29yZSIpICsgdGhlbWVfdm9pZCgpICMrIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQodGl0bGU9IkFkai5aIHNjb3JlIikpCgpsaWJyYXJ5KHBhdGNod29yaykKcDErcDIKYGBgCgpERUcgYW5hbHlzaXMKCiNjYW8kZXN0aW1hdGVERVBlckNlbGxUeXBlKG4uY29yZXMgPSAxMDAsIG5hbWUgPSAiZWRnZVIiLCBuLmNlbGxzLnN1YnNhbXBsZSA9IDUsIHJlc2FtcGxpbmcubWV0aG9kID0gImJvb3RzdHJhcCIsIG4ucmVzYW1wbGluZ3MgPSAyMCkKCgpgYGB7cn0KI2NhbyRlc3RpbWF0ZURFUGVyQ2VsbFR5cGUobi5jb3JlcyA9IDEwMCwgbmFtZSA9ICJlZGdlUiIsIG4uY2VsbHMuc3Vic2FtcGxlID0gNSwgcmVzYW1wbGluZy5tZXRob2QgPSAiYm9vdHN0cmFwIiwgbi5yZXNhbXBsaW5ncyA9IDIwKQojY2FvJHRlc3QucmVzdWx0cyRlZGdlUjIgPC0gY2FvJHRlc3QucmVzdWx0cyRlZGdlUiAlPiUgbGFwcGx5KGZ1bmN0aW9uKHgpewojICB4JHJlcyA8LSBuYS5vbWl0KHgkcmVzW29yZGVyKHgkcmVzJHN0YWIubWVkaWFuLnJhbmspLF0pCiMgIHgkcmVzJFogPC0ge3JhbmsoeCRyZXMkc3RhYi5tZWRpYW4ucmFuayklPiUgcmV2fSAqIHNpZ24oeCRyZXMkbG9nMkZvbGRDaGFuZ2UpCiMgIHJldHVybih4KQojfSkKCm5hbWVzKGNhbyR0ZXN0LnJlc3VsdHMkZWRnZVIyKSA8LSByZWNvZGUoY2FvJHRlc3QucmVzdWx0cyRlZGdlUjIgJT4lIG5hbWVzLCAhISFyZWN2ZWMpCmNhbyRwbG90TnVtYmVyT2ZERUdlbmVzKG5hbWUgPSAiZWRnZVIyIikKYGBgCmBgYHtyfQpjYW8kdGVzdC5yZXN1bHRzJGVkZ2VSMiAlPiUgbGFwcGx5KCJbWyIsICJyZXMiKSAlPiUgcmJpbmRsaXN0KC4sIGlkY29sID0gImNlbGx0eXBlIikKYGBgCmBgYHtyfQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoZ2dkaXN0KQpkYXR2b2wgPC0gY2FvJHRlc3QucmVzdWx0cyRlZGdlUjIkU3N0X0Nob2RsJHJlcyAlPiUgZGF0YS50YWJsZQoKcCA8LSBkYXR2b2wgJT4lIGdncGxvdCguLCBhZXMoeCA9IGxvZzEwKHN0YWIubWVkaWFuLnJhbmspLCB5ID0gbG9nMkZvbGRDaGFuZ2UsIGFscGhhID0gKGFicyhsb2cyRm9sZENoYW5nZSkpKSkgKyAKICBnZW9tX3BvaW50KAogICAgICAgIGFlcyhjb2xvcj0gSShpZmVsc2UoYWJzKGxvZzJGb2xkQ2hhbmdlKSA+MSwgInN0ZWVsYmx1ZTMiLCAnZ3JleTgwJykpLCBzaXplID0gKENlbGxGcmFjKSkpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLTEsIGxpbmV0eXBlID0gImRhc2hlZCIpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fbGFiZWxfcmVwZWwoZGF0YSA9IGRhdHZvbFthYnMobG9nMkZvbGRDaGFuZ2UpID4gMSxdICU+JSBoZWFkKDIwKSwgCiAgICAgICAgICAgICAgICAgICBhZXMobGFiZWwgPSBHZW5lKSwgCiAgICAgICAgICAgICAgICAgICBtYXgub3ZlcmxhcHMgPSAzMCwgCiAgICAgICAgICAgICAgICAgICBzaXplID0gMywgYWxwaGEgPSAxKSArIHlsaW0oLTQsIDQpICArIHRoZW1lX3RpZHliYXllcygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsgCiAgeGxhYigiU3RhYmlsaXR5IC0gbWVkaWFuIHJhbmsgb2YgZ2VuZSBieSBwIHZhbHVlIGFjcm9zcyByZXNhbXBsaW5ncyIpICsgeWxhYigiTEZDIikgCgpnZ3Jhc3RyOjpyYXN0ZXJpemUocCwgZHBpID0gMzAwKQpgYGAKCkdlbmUgb250b2xvZ3kKCiNjYW8kZXN0aW1hdGVPbnRvbG9neSh0eXBlID0gIkdTRUEiLCBuYW1lID0gIkdTRUEiLCBvcmcuZGIgPW9yZy5NbS5lZy5kYiwgdmVyYm9zZSA9IFQsIG4uY29yZXMgPSAyMDAsIGRlLm5hbWUgPSAiZWRnZVIyIikKCmBgYHtyfQojY2FvJGVzdGltYXRlT250b2xvZ3kodHlwZSA9ICJHU0VBIiwgbmFtZSA9ICJHU0VBIiwgb3JnLmRiID1vcmcuTW0uZWcuZGIsIHZlcmJvc2UgPSBULCBuLmNvcmVzID0gMjAwLCBkZS5uYW1lID0gImVkZ2VSMiIpCmNhbyRwbG90T250b2xvZ3lIZWF0bWFwKG5hbWUgPSAiR1NFQSIsIGdlbmVzID0gImFsbCIpCmBgYAoKYGBge3J9CnNzdGNob2RsYWxsIDwtIHNldE5hbWVzKGNhbyR0ZXN0LnJlc3VsdHMkR1NFQSRyZXMkU3N0X0Nob2RsICU+JSBsYXBwbHkoZnVuY3Rpb24oeCkgeEByZXN1bHQpLCBjKCJCUCIsICJDQyIsICJNRiIpKSAlPiUgcmJpbmRsaXN0KGlkY29sID0gInN1YnR5cGUiKQpzc3RjaG9kbGFsbCRwYWRqMiA8LSBzc3RjaG9kbGFsbFtvcmRlcihwdmFsdWUpLHB2YWx1ZV0gJT4lIHAuYWRqdXN0KG1ldGhvZCA9ICJCSCIpCgpwIDwtIGdncmFzdHI6OnJhc3Rlcml6ZShzc3RjaG9kbGFsbCAlPiUgZ2dwbG90KC4sIGFlcyh4ID0gTkVTLCAgeSA9IC1sb2cxMChwYWRqMiksIGNvbG9yID0gcGFkajIsIGFscGhhID0gLWxvZzEwKHBhZGoyKSwgc2l6ZSA9IC1sb2cxMChwYWRqMikpKSArIAogIGdlb21fcG9pbnQoKSArIHNjYWxlX3NpemUocmFuZ2UgPSBjKDAsIDIpKSArIAogIGdlb21fbGFiZWxfcmVwZWwoZGF0YSA9IHNzdGNob2RsYWxsW3BhZGoyIDwgMC4wNSxdLCBhZXMobGFiZWwgPSBEZXNjcmlwdGlvbiksIHNpemUgPSAyLCBhbHBoYSA9IDEsIGNvbG9yID0gImJsYWNrIikgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLjMsIGxpbmV0eXBlID0gImRhc2hlZCIpICsgdGhlbWVfdGlkeWJheWVzKCkgKyAKICAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGhpZ2ggPSAibGlnaHRzdGVlbGJsdWUyIiwgbWlkID0gIndoaXRlIiwgbG93ID0gInN0ZWVsYmx1ZTQiLCBtaWRwb2ludCA9IDAuNSksIAogIGRwaSA9IDMwMCkKCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ21hZ25pZnkpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ2ZvcmNlKQpsaWJyYXJ5KGdyaWQpCgpwMiA8LSBwICsKICBmYWNldF96b29tKHkgPSBwYWRqMiA8IDAuMDUsIHggPSBORVMgPCAtMS41LCBzcGxpdCA9IEYsIHpvb20uc2l6ZSA9IDIpCgpwMgpgYGAKYGBge3J9CiNxc2F2ZShjYW8sICJjYW9faW5oLnFzIikKYGBgCg==